/**
 * 
 */
package com.vivid.dynamics.junit;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;

/**
 *	Simple Template acting as the base class for JUnit 4.x test case(s)
 *	<ul>
 *		<li>provided a StringBuilder for building stdOut messages</li>
 *		<li>provided hooks to auto clear and print out the above messages to the Log4J Logger</li>
 *	</ul>
 *	<b>PS</b>. However, implementation should set the Log4J logger before any printout actions being done.
 *
 * @author jason
 * created at:: Jul 28, 2011 2:14:39 PM
 */
public abstract class JUnitTemplate {
	/**
	 * log4j logger for logging purpose; should use this logger instead of 
	 * direct System.out.println()
	 */
	protected Logger logger;
	/**
	 * the message holder for each method; this holder's contents will be 
	 * logged out to the associated Logger instance 
	 * @see #logger 
	 */
	protected StringBuilder sb;
	
	/**
	 * actions just after class being created. 
	 * Default does nothing, override when necessary 
	 * 
	 * @author jason
	 * created at:: Jul 28, 2011  2:21:54 PM
	 */
	@BeforeClass
	public static void doBeforeClassAction() {
		
	}
	
	/**
	 * actions just before class instance being destroyed.
	 * Default does nothing, override when necessary
	 * 
	 * @author jason
	 * created at:: Jul 28, 2011  2:22:25 PM
	 */
	@AfterClass
	public static void doAfterClassAction() {
		
	}
	
	/**
	 * actions just before any test method being executed.
	 * Default does nothing, override when necessary
	 * 
	 * @author jason
	 * created at:: Jul 28, 2011  2:23:09 PM
	 */
	@Before
	public void doBeforeAction() {
		// any pre actions...
	}
	
	/**
	 * actions just after any test method being executed.
	 * Default will check whether the StringBuilder has contents; if true
	 * will direct them to the associated Logger.<p/>
	 * 
	 * The logging level used will be "DEBUG", therefore any messages lower
	 * priority than DEBUG won't be logged (ie. TRACE level)
	 * 
	 * @see #logger
	 * @see #sb
	 * 
	 * @author jason
	 * created at:: Jul 28, 2011  2:23:30 PM
	 */
	@After
	public void doAfterAction() {
		if (this.sb.length()>0) {
			if (logger.isDebugEnabled()) {
				logger.debug(this.sb.toString());
			}
			this.sb.delete(0, this.sb.length());
		}
	}
	
	/**
	 * ctor. Create a Logger of this class as well
	 */
	public JUnitTemplate() {
		this(JUnitTemplate.class);
	}
	
	/**
	 * ctor
	 * @param pLoggerClass
	 */
	@SuppressWarnings(value = { "unchecked" })
	public JUnitTemplate(final Class pLoggerClass) {
		this.sb=new StringBuilder(1500);
		this.logger=Logger.getLogger(pLoggerClass);
	}
	
	/**
	 * helper method to iterate a Collection (ie. Set, List) and create the 
	 * String output for debugging
	 * @param pSB
	 * @param pCollection
	 * @author jason
	 * created at:: Aug 9, 2011  2:37:31 PM
	 */
	@SuppressWarnings("rawtypes")
	public void createToStringForCollections(final StringBuilder pSB, final Collection pCollection) {
		this.createToStringForCollections(pSB, pCollection, 1);
	}
	
	/**
	 * helper method to iterate a Collection (ie. Set, List) and create the 
	 * String output for debugging<br/>
	 * the param pTabs is for creating the no. of tabs "\t" for the output
	 * @param pSB
	 * @param pCollection
	 * @author jason
	 * created at:: Aug 9, 2011  2:37:31 PM
	 */
	@SuppressWarnings("rawtypes")
	public void createToStringForCollections(final StringBuilder pSB, final Collection pCollection, int pTabs) {
		if (pSB!=null && pCollection!=null) {
			StringBuilder pTabMsg=new StringBuilder(50);
			int aIdx=0;
			Iterator aIter=pCollection.iterator();
			
			pTabMsg.append("\r\n");
			if (pTabs>0) {
				for (int i=0; i<pTabs; i++) {
					pTabMsg.append("\t");
				}
			} else {
				pTabMsg.append("\t");
			}
			
			while(aIter.hasNext()) {
				/*if (aIdx>0) {
					pSB.append(pTabMsg.toString());
				}*/
				pSB.append(pTabMsg.toString());
				pSB.append(aIdx+1).append(") ").append(aIter.next());
				aIdx++;
			}
		}	// end if
	}
	
	/**
	 * helper method to iterate a Map (ie. HashSet, Hashtable) and create the 
	 * String output for debugging
	 * @param pSB
	 * @param pMap
	 * @author jason
	 * created at:: Aug 9, 2011  2:41:16 PM
	 */
	@SuppressWarnings("rawtypes")
	public void createToStringForMaps(final StringBuilder pSB, final Map pMap) {
		this.createToStringForMaps(pSB, pMap, 1);
	}
	/**
	 * helper method to iterate a Map (ie. HashSet, Hashtable) and create the 
	 * String output for debugging<br/>
	 * the param pTabs is for creating the no. of tabs "\t" for the output
	 * @param pSB
	 * @param pMap
	 * @author jason
	 * created at:: Aug 9, 2011  2:41:16 PM
	 */
	@SuppressWarnings("rawtypes")
	public void createToStringForMaps(final StringBuilder pSB, final Map pMap, int pTabs) {
		if (pSB!=null && pMap!=null) {
			StringBuilder pTabMsg=new StringBuilder(50);
			int aIdx=0;
			Set aKeys=pMap.keySet();
			Iterator aKeyIter=aKeys.iterator();
			
			pTabMsg.append("\r\n");
			if (pTabs>0) {
				for (int i=0; i<pTabs; i++) {
					pTabMsg.append("\t");
				}
			} else {
				pTabMsg.append("\t");
			}
			
			while (aKeyIter.hasNext()) {
				/*if (aIdx>0) {
					pSB.append(pTabMsg.toString());
				}*/
				pSB.append(pTabMsg.toString());
				pSB.append(aIdx+1).append(") ").append(pMap.get(aKeyIter.next())); 
				aIdx++;
			}
		}	// end if
	}
	
}
